package com.ruyuan.eshop.construction.service.impl;

import com.alibaba.fastjson.JSON;
import com.ruyuan.eshop.common.core.PageResult;
import com.ruyuan.eshop.common.domain.DiffValue;
import com.ruyuan.eshop.common.enums.construction.AuditStatusEnum;
import com.ruyuan.eshop.common.enums.construction.AuditTypeEnum;
import com.ruyuan.eshop.common.utils.DiffFieldUtil;
import com.ruyuan.eshop.construction.builder.FullDraftData;
import com.ruyuan.eshop.construction.builder.FullProductData;
import com.ruyuan.eshop.construction.domain.dto.AuditInfoDTO;
import com.ruyuan.eshop.construction.domain.dto.DraftDetailDTO;
import com.ruyuan.eshop.construction.domain.dto.DraftMainDTO;
import com.ruyuan.eshop.construction.domain.dto.ExecAuditDTO;
import com.ruyuan.eshop.construction.domain.entity.AuditInfoDO;
import com.ruyuan.eshop.construction.domain.entity.AuditorListConfigDO;
import com.ruyuan.eshop.construction.domain.entity.DraftMainDO;
import com.ruyuan.eshop.construction.domain.entity.ItemInfoDO;
import com.ruyuan.eshop.construction.domain.entity.SkuInfoDO;
import com.ruyuan.eshop.construction.domain.request.AuditRequest;
import com.ruyuan.eshop.construction.domain.request.QueryDraftRequest;
import com.ruyuan.eshop.construction.domain.request.QueryTodoListRequest;
import com.ruyuan.eshop.construction.repository.ProductAuditRepository;
import com.ruyuan.eshop.construction.repository.ProductInfoRepository;
import com.ruyuan.eshop.construction.service.AuditService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author zhonghuashishan
 * @version 1.0
 */
@Service
@Slf4j
public class AuditServiceImpl implements AuditService {

    @Resource
    private ProductAuditRepository productAuditRepository;

    @Resource
    private ProductInfoRepository productInfoRepository;

    @Value("${diff.fields.item}")
    private List<String> itemDiffFields;

    @Value("${diff.fields.sku}")
    private List<String> skuDiffFields;


    /**
     * 验证商品是否需要审核
     * @param fullProductData
     * @param createFlag
     * @return
     */
    @Override
    public Boolean needAudit(FullProductData fullProductData, Boolean createFlag) {
        return productAuditRepository.needAudit(fullProductData, createFlag);
    }

    /**
     *  保存草稿信息
     * @param fullDraftData
     */
    @Override
    public void saveDraft(FullDraftData fullDraftData) {
        productAuditRepository.saveDraft(fullDraftData);
    }

    /**
     * 获取审核的代办列表
     * @param queryTodoListRequest
     * @return
     */
    @Override
    public PageResult<AuditInfoDTO> getTodoList(QueryTodoListRequest queryTodoListRequest) {
        // 获取用户审核角色
        AuditorListConfigDO auditor = productAuditRepository.getAuditorRuleByUserId(queryTodoListRequest.getUserId());
        // 返回待办列表
        return productAuditRepository.pageResult(queryTodoListRequest, auditor);
    }

    /**
     * 查询草稿详情信息
     * @param queryDraftRequest
     * @return
     */
    @Override
    public DraftDetailDTO getDraftDetail(QueryDraftRequest queryDraftRequest) {
        // 草稿详情信息
        DraftDetailDTO draftDetailDTO = productAuditRepository.getDraftDetail(queryDraftRequest.getTicketId());
        // 构建需要比较不同的字段数据
        buildDiffChangeField(draftDetailDTO);
        return draftDetailDTO;
    }

    /**
     *  执行审核
     * @param auditRequest
     * @return
     */
    @Transactional
    @Override
    public ExecAuditDTO execAudit(AuditRequest auditRequest) {
        // 验证是否有可以审核，并填充审核信息
        AuditInfoDTO auditInfoDTO = productAuditRepository.checkAudit(auditRequest);
        // 执行审核
        execGoodsAudit(auditRequest, auditInfoDTO);
        // 处理审核的信息DB变更
        productAuditRepository.updateAudit(auditRequest,auditInfoDTO);

        return new ExecAuditDTO(Boolean.TRUE);
    }

    /**
     * 商品审核
     * @param auditRequest
     * @param auditInfoDTO
     */
    private void execGoodsAudit(AuditRequest auditRequest, AuditInfoDTO auditInfoDTO) {
        DraftMainDTO draftMainDTO = auditInfoDTO.getDraftMainDTO();
        Integer ticketType = auditInfoDTO.getTicketType();
        // 如果是审批通过，则需要更改正式表的数据
        if (Objects.equals(auditRequest.getAuditStatus(), AuditStatusEnum.PASS.getCode())){
            FullProductData fullProductData = JSON.parseObject(draftMainDTO.getFeatures(), FullProductData.class);
            // 建品审核
            if (Objects.equals(ticketType, AuditTypeEnum.GOODS.getCode())){
                fullProductData.getItemInfoDO().setVersionId(draftMainDTO.getVersionId());
                // 产品信息入库。版本号小于等于1，表示新增，否则表示修改
                if (fullProductData.getItemInfoDO().getVersionId() <= 1){
                    productInfoRepository.saveItemInfo(fullProductData);
                } else {
                    productInfoRepository.updateItemInfo(fullProductData);
                }
            }else if (Objects.equals(ticketType, AuditTypeEnum.PRICE.getCode())){
                SkuInfoDO skuInfoDO = fullProductData.getSkuInfoDOList().get(0);
                productInfoRepository.saveRecord(skuInfoDO);
            }
        }
    }

    /**
     * 构建需要比较不同的字段的数据
     *
     * @param draftDetailDTO
     * @return void
     * @author zhonghuashishan
     */
    private void buildDiffChangeField(DraftDetailDTO draftDetailDTO) {
        // 草稿主表信息
        DraftMainDTO draftMainDTO = draftDetailDTO.getDraftMainDTO();
        // 修改后的商品数据
        FullProductData fullProductData = JSON.parseObject(draftMainDTO.getFeatures(), FullProductData.class);

        // 商品新增时，item版本号是0，草稿表中的版本号是item表中的版本号加1。所以此时判断草稿表中的版本号是小于等于1表示新增数据。
        if (draftMainDTO.getVersionId() <= 1){
            buildAddDiff(fullProductData, draftDetailDTO);
        }else {
            buildUpdateDiff(fullProductData,draftDetailDTO);
        }
    }

    /**
     * 填充修改的 商品差异变化信息
     * @param fullProductData
     * @param draftDetailDTO
     */
    private void buildUpdateDiff(FullProductData fullProductData,DraftDetailDTO draftDetailDTO){
        // item信息
        ItemInfoDO itemInfoDO = fullProductData.getItemInfoDO();

        // 先查询修改前itemInfoDO和修改前的skuInfoDOList，再比较变更值
        ItemInfoDO oldItemInfoDO = productInfoRepository.getItemByItemId(itemInfoDO.getItemId());
        List<DiffValue> itemDiffValues = DiffFieldUtil.buildDiffField(itemInfoDO, oldItemInfoDO, itemDiffFields);

        List<SkuInfoDO> oldSkuInfoDOList = productInfoRepository.listSkuByItemId(itemInfoDO.getItemId());

        List<SkuInfoDO> skuInfoDOList = fullProductData.getSkuInfoDOList();

        List<DiffValue> skuDiffValues;

        // skuList diff 存放Map集合
        Map<String, List<DiffValue>> skuDiffFieldsMap = new HashMap<>();
        // 旧的商品集合转换
        Map<String,SkuInfoDO> oldMap = oldSkuInfoDOList.stream().collect(Collectors.toMap(SkuInfoDO::getSkuId, e -> e));

        for (SkuInfoDO skuInfoDO : skuInfoDOList) {
            if (oldMap.containsKey(skuInfoDO.getSkuId())){
                SkuInfoDO oldSkuInfoDO = oldMap.get(skuInfoDO.getSkuId());
                skuDiffValues = DiffFieldUtil.buildDiffField(skuInfoDO, oldSkuInfoDO, skuDiffFields);
                if (!CollectionUtils.isEmpty(skuDiffValues)){
                    skuDiffFieldsMap.put(skuInfoDO.getSkuId(), skuDiffValues);
                }
            }
        }
        // 填充修改的商品信息
        buildDiffInfo(itemDiffValues, skuDiffFieldsMap, draftDetailDTO);
    }

    /**
     *  填充新增的 商品差异变化信息
     * @param fullProductData
     * @param draftDetailDTO
     */
    private void buildAddDiff(FullProductData fullProductData,DraftDetailDTO draftDetailDTO){
        // item信息
        ItemInfoDO itemInfoDO = fullProductData.getItemInfoDO();

        List<DiffValue> itemDiffValues = DiffFieldUtil.buildDiffField(itemInfoDO, null, itemDiffFields);

        // skuList diff 存放Map集合
        Map<String, List<DiffValue>> skuDiffFieldsMap = null;
        // sku信息
        List<SkuInfoDO> skuInfoDOList = fullProductData.getSkuInfoDOList();
        if (!CollectionUtils.isEmpty(skuInfoDOList)){
            skuDiffFieldsMap = new HashMap<>(skuInfoDOList.size());
            for (SkuInfoDO skuInfoDO : skuInfoDOList) {
                List<DiffValue> skuDiffValues = DiffFieldUtil.buildDiffField(skuInfoDO, null, skuDiffFields);
                if (!CollectionUtils.isEmpty(skuDiffValues)){
                    skuDiffFieldsMap.put(skuInfoDO.getSkuId(), skuDiffValues);
                }
            }
        }
        //填充商品数据变更的差异信息
        buildDiffInfo(itemDiffValues,skuDiffFieldsMap,draftDetailDTO);

    }

    /**
     * 填充商品数据变更的差异信息
     * @param itemDiffValues
     * @param skuDiffFieldsMap
     * @param draftDetailDTO
     */
    private void buildDiffInfo(List<DiffValue> itemDiffValues,
                               Map<String, List<DiffValue>> skuDiffFieldsMap,
                               DraftDetailDTO draftDetailDTO){
        // item变更字段
        if (!CollectionUtils.isEmpty(itemDiffValues)) {
            draftDetailDTO.setItemDiffFields(itemDiffValues);
        }

        // sku变更字段
        if (!CollectionUtils.isEmpty(skuDiffFieldsMap)) {
            draftDetailDTO.setSkuDiffFields(skuDiffFieldsMap);
        }
    }
}
